using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace stsdev {

    public class CabDdfBuilder {

        public static void Create(string FilePath) {
            // Added 081612 wictor - check if the file is read-only, if so the issue a warning that fits into Visual Studio Errors List
            FileInfo fileInfo = new FileInfo(FilePath);
            if (fileInfo.Exists && fileInfo.IsReadOnly) {
                Console.WriteLine(string.Format("{0} : warning : Unable to update the DDf file. File is read-only", FilePath));
                return;
            }
            // End 080612 Addition
            // Modified 080612 wictor - added using statement
            using (StreamWriter writer = new StreamWriter(FilePath)) {
                writer.WriteLine("; Generated by STSDEV at " + DateTime.Now.ToString());
                writer.WriteLine();
                writer.WriteLine(".OPTION EXPLICIT");
                writer.WriteLine(".Set CabinetNameTemplate=" + SolutionBuilder.SolutionName + ".wsp");
                writer.WriteLine(".set DiskDirectoryTemplate=CDROM");
                writer.WriteLine(".Set CompressionType=MSZIP");
                writer.WriteLine(".Set UniqueFiles=off");
                writer.WriteLine(".Set Cabinet=on");
                writer.WriteLine(".Set CabinetFileCountThreshold=0");
                writer.WriteLine(".Set FolderFileCountThreshold=0");
                writer.WriteLine(".Set FolderSizeThreshold=0");
                writer.WriteLine(".Set MaxCabinetSize=0");
                writer.WriteLine(".Set MaxDiskFileCount=0");
                writer.WriteLine(".Set MaxDiskSize=0");
                writer.WriteLine(".Set DiskDirectory1=" + Globals.DeploymentFilesFolder);
                writer.WriteLine();

                writer.WriteLine(";*** Solution manifest");
                writer.WriteLine(Globals.DeploymentFilesFolder + @"\manifest.xml");

                if (SolutionBuilder.Assemblies.Count > 0) {
                    writer.WriteLine("");
                    writer.WriteLine(";*** Assembly files");
                    foreach (SolutionAssembly asm in SolutionBuilder.Assemblies) {
                        // Modified 4/2/2009 - bphillips - Release dll was not being added to the WSP file.
                        if (!string.IsNullOrEmpty(SolutionBuilder.ConfigurationName) && SolutionBuilder.ConfigurationName.ToLower().StartsWith("release")) {
                            writer.WriteLine(@"bin/release/" + asm.Location);
                        } else {
                            writer.WriteLine(@"bin/debug/" + asm.Location);
                        }
                        // End of Modified 4/2/2009 - bphillips
                    }
                }

                if (Directory.Exists(Globals.FeaturesFolder)) {
                    WriteFeatureFiles(writer);
                    writer.WriteLine();
                }

                if (Directory.Exists(Globals.TemplatesFolder)) {
                    // write TemplateFiles
                    writer.WriteLine("");
                    writer.WriteLine(";***********************************");
                    writer.WriteLine(";*** Begin TemplateFiles section ***");
                    writer.WriteLine(";***********************************");
                    WriteTemplateFiles(writer);
                    writer.WriteLine();
                }

                if (Directory.Exists(Globals.IsapiFolder) || Directory.Exists(Globals.ResourcesFolder)) {
                    // write RootFiles
                    writer.WriteLine("");
                    writer.WriteLine(";*******************************");
                    writer.WriteLine(";*** Begin RootFiles section ***");
                    writer.WriteLine(";*******************************");
                    WriteRootFiles(writer);
                    writer.WriteLine();
                }

                writer.Close();
            }

        }

        static void WriteFeatureFiles(StreamWriter writer) {
            // Modified 20090715 - bphillips - Reverted to 1.3 version functionality to not required feature files to be listed in SolutionConfig.xml.
            EnumerateFeatureDirectory(writer, Globals.FeaturesFolder);
        }

        static void EnumerateFeatureDirectory(StreamWriter writer, string path) {
            if ((Directory.GetFiles(path).Length > 0) &&
                 (path != Globals.FeaturesFolder)) {
                // write files
                int PathOffset = (Globals.FeaturesFolder + @"\").Length;
                writer.WriteLine();
                writer.WriteLine(";*** add files for " + path.Substring(PathOffset) + " feature");
                writer.WriteLine(".Set DestinationDir=" + path.Substring(PathOffset));
                foreach (string file in Directory.GetFiles(path)) {

                    // Addition 080612 wictor - ignore hidden or source control files
                    if (isValidDdfFile(file)) {

                        if (!file.Contains(" ")) {
                            writer.WriteLine(file);
                        } else {
                            writer.WriteLine(@"""" + file + @"""");
                        }
                    }
                }

            }

            foreach (string folder in Directory.GetDirectories(path)) {
                // Addition 080612 wictor - ignore hidden folders
                if (isValidDirectory(folder)) {
                    EnumerateFeatureDirectory(writer, folder);
                }
            }
        }

        static void WriteTemplateFiles(StreamWriter writer) {
            EnumerateTemplateDirectory(writer, Globals.TemplatesFolder);
        }

        static void EnumerateTemplateDirectory(StreamWriter writer, string path) {
            // write files
            if ((Directory.GetFiles(path).Length > 0) &&
                (path != Globals.TemplatesFolder)) {
                int PathOffset = (Globals.TemplatesFolder + @"\").Length;
                writer.WriteLine("");
                writer.WriteLine(".Set DestinationDir=" + path.Substring(PathOffset));
                foreach (string file in Directory.GetFiles(path)) {

                    // Addition 080612 wictor - ignore hidden or source control files
                    if (isValidDdfFile(file)) {
                        if (ManifestBuilder.IsAFeatureFile(file)) continue;
                        if (!file.Contains(" ")) {
                            writer.WriteLine(file);
                        } else {
                            writer.WriteLine(@"""" + file + @"""");
                        }
                    }
                }
            }

            foreach (string folder in Directory.GetDirectories(path)) {
                // Addition 080612 wictor - ignore hidden folders
                if (isValidDirectory(folder)) {
                    EnumerateTemplateDirectory(writer, folder);
                }
            }
        }

        static void WriteRootFiles(StreamWriter writer) {
            EnumerateRootFilesDirectory(writer, Globals.RootFilesFolder);
        }

        static void EnumerateRootFilesDirectory(StreamWriter writer, string path) {
            // do nothing for folders in TEMPLATE folder
            if (path.Contains("TEMPLATE")) {
                return;
            }
            // write files
            if ((Directory.GetFiles(path).Length > 0) &&
                (path != Globals.RootFilesFolder)) {
                int PathOffset = (Globals.RootFilesFolder + @"\").Length;
                writer.WriteLine("");
                writer.WriteLine(".Set DestinationDir=" + path.Substring(PathOffset));
            }
            foreach (string file in Directory.GetFiles(path)) {

                // Addition 080612 wictor - ignore hidden or source control files
                if (isValidDdfFile(file)) {

                    if (!file.Contains(" ")) {
                        writer.WriteLine(file);
                    } else {
                        writer.WriteLine(@"""" + file + @"""");
                    }
                }
            }

            foreach (string folder in Directory.GetDirectories(path)) {
                // Addition 080612 wictor - ignore hidden folders
                if (isValidDirectory(folder)) {
                    EnumerateRootFilesDirectory(writer, folder);
                }
            }
        }



        static void WriteAssembly(XmlWriter writer, string file, AssemblyDeploymentTarget target) {
            writer.WriteStartElement("Assembly");
            writer.WriteStartAttribute("Location");
            writer.WriteValue(file);
            writer.WriteEndAttribute();
            writer.WriteStartAttribute("DeploymentTarget");
            writer.WriteValue(target.ToString());
            writer.WriteEndAttribute();
            writer.WriteEndElement();
        }

        // Added 080612 wictor - Added
        /// <summary>
        /// Checks if the file is valid for inclusion in the Ddf file
        /// </summary>
        /// <param name="file">Path to the file to check</param>
        /// <returns>Returns false if the file is hidden or have an extension of .scc, otherwise false</returns>
        private static bool isValidDdfFile(string file) {
            FileInfo fileInfo = new FileInfo(file);

            // Modified 20090403 - bphillips - Ignore code files.
            return !(((fileInfo.Attributes & FileAttributes.Hidden) != 0)
                || (fileInfo.Extension.ToLower() == ".scc")
                || (fileInfo.Extension.ToLower() == ".vb")
                || (fileInfo.Extension.ToLower() == ".cs"));
        }

        private static bool isValidDirectory(string path) {
            DirectoryInfo directoryInfo = new DirectoryInfo(path);
            return !((directoryInfo.Attributes & FileAttributes.Hidden) != 0);
        }
        // End 080612 Addition
    }
}
